﻿using System;
using UnityEngine;
using UnityEngine.Rendering;

namespace ProjScan.Submodules.Effects_Play_Check
{
    internal class OverdrawMonitor
    {
        public Camera overdrawCamera;

        private int textureWidth = 512;

        private int textureHeight = 512;

        private string unityRenderingPipeline = "UnityEngine.Rendering.Universal";

        private RenderTexture renderTexture;

        private ProjScanEffectEvlaData _projScanEffectEvlaData;

        public OverDrawUrpSupport urpSupport = new OverDrawUrpSupport();

        public static OverdrawMonitor Instance = new OverdrawMonitor();

        public bool urpModeEnabled = false;

        public Camera mainCamera;

        private OverdrawMonitor()
        {
            if (NamespaceValidator.CheckNamespaceExists(unityRenderingPipeline) && GraphicsSettings.renderPipelineAsset != null)
            {
                Debug.Log("UrpMode On");
                urpSupport.LoadUrpAssembly();
                urpSupport.SetRendererFeatureToData();
                urpSupport.SetUrpToSrpSetting();
                urpModeEnabled = true;
            }
            else
            {
                urpModeEnabled = false;
            }

            SetupOverdrawCamera();
        }

        public void RemoveLastFeature()
        {
            if (NamespaceValidator.CheckNamespaceExists(unityRenderingPipeline) && GraphicsSettings.renderPipelineAsset != null)
            {
                urpSupport.RemoveLastFeature();
            }
        }

        public void InitializeRenderTexture()
        {
            _projScanEffectEvlaData = new ProjScanEffectEvlaData();
            renderTexture = new RenderTexture(textureWidth, textureHeight, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
        }

        public ProjScanEffectEvlaData GetFrameInfoCollector()
        {
            return _projScanEffectEvlaData;
        }

        public void SetupOverdrawCamera()
        {
            overdrawCamera = GameObject.Find("OverdrawCamera").GetComponent<Camera>();
            overdrawCamera.SetReplacementShader(Shader.Find("ParticleEffectProfiler/OverDraw"), "");
            if (urpModeEnabled)
            {
                mainCamera = GameObject.Find("Main Camera").GetComponent<Camera>();
                mainCamera.enabled = false;
                overdrawCamera.enabled = true;
            }
        }

        public void RenderOverdraw()
        {
            RenderOverdrawCore();
        }

        public void RenderOverdrawCore()
        {
            int pixelCount = 0;
            int colorIntensity = 0;
            RenderAndScan(out pixelCount, out colorIntensity);
            UpdateFrameInfo(pixelCount, colorIntensity);
        }

        public void RenderAndScan(out int pixelCount, out int colorIntensity)
        {
            RenderTexture active = RenderTexture.active;
            overdrawCamera.targetTexture = renderTexture;
            overdrawCamera.Render();
            RenderTexture.active = renderTexture;
            Texture2D texture2D = new Texture2D(renderTexture.width, renderTexture.height, TextureFormat.RGBA32, mipChain: false);
            texture2D.ReadPixels(new Rect(0f, 0f, renderTexture.width, renderTexture.height), 0, 0);
            AnalyzeImageColors(texture2D, out pixelCount, out colorIntensity);
            RenderTexture.active = active;
            UnityEngine.Object.DestroyImmediate(texture2D);
            renderTexture.Release();
            overdrawCamera.targetTexture = null;
        }

        public void AnalyzeImageColors(Texture2D texture, out int pixelCount, out int colorIntensity)
        {
            int width = texture.width;
            int height = texture.height;
            Color[] pixels = texture.GetPixels();
            int num = 0;
            pixelCount = 0;
            colorIntensity = 0;
            for (int i = 0; i < height; i++)
            {
                for (int j = 0; j < width; j++)
                {
                    float r = pixels[num].r;
                    float g = pixels[num].g;
                    float b = pixels[num].b;
                    if (!IsPixelTransparent(r, g, b))
                    {
                        pixelCount++;
                    }

                    int num2 = CalculateGreenIntensity(r, g, b);
                    colorIntensity += num2;
                    num++;
                }
            }
        }

        public int CalculateGreenIntensity(float red, float green, float blue)
        {
            return Convert.ToInt32((double)green / 0.04);
        }

        public bool IsPixelTransparent(float red, float green, float blue)
        {
            return red == 0f && green == 0f && blue == 0f;
        }

        public void UpdateFrameInfo(int pixelCount, int colorIntensity)
        {
            if (pixelCount > 0 || colorIntensity > 0)
            {
                _projScanEffectEvlaData.pixTotal += pixelCount;
                _projScanEffectEvlaData.pixActualDrawTotal += colorIntensity;
                _projScanEffectEvlaData.pixDrawTimes++;
            }
        }
    }
}